%
% Copyright (c) 2022 Kangwei Xia
% Released under the LaTeX Project Public License v1.3c License.
% Repository: https://gitee.com/xkwxdyy/xchoices
% Repository: https://github.com/xkwxdyy/xchoices
%

\NeedsTeXFormat{LaTeX2e}[2018/04/01]

\RequirePackage{expl3}
\RequirePackage { l3keys2e, xparse }

\ProvidesExplPackage {xchoices} {2022-02-03} {0.1.1}
  {
    A package for flexibly LaTeXing choice items based on hlist environment and coffin.
    Kangwei Xia
    <kangweixia_xdyy@163.com>
  }

% 检测宏包
\msg_new:nnn { xchoices } { l3-too-old }
  {
    Package~ "#1"~ is~ too~ old. \\\\
    Please~ update~ an~ up-to-date~ version~ of~ the~ bundles \\
    "l3kernel"~ and~ "l3packages"~ using~ your~ TeX~ package \\
    manager~ or~ from~ CTAN.
  }
\clist_map_inline:nn { expl3, xparse, l3keys2e }
  {
    \@ifpackagelater {#1} { 2018/05/12 }
      { } { \msg_error:nnn { xchoices } { l3-too-old } {#1} }
  }




% 加载宏包
\RequirePackage{ hlist }     % 对位宏包
\RequirePackage{ varwidth }
\RequirePackage{ tikz }      % 绘制带圈数字，\quan需要
\RequirePackage{ xcolor }    % 颜色
\RequirePackage{ linegoal }  % 获取当前行剩下的距离，\xparen需要


%%%% 变量声明 %%%%
\seq_new:N \l__xchoices_items_seq   % 用于储存最终分隔开的选项信息
\tl_new:N \l__xchoices_items_pre_check_tl   % 用于检测输入的结尾是否含有&&
\str_new:N \l__xchoices_items_pre_check_last_item_str  % 用于检测输入的最后一个是否是&
\dim_new:N \l__xchoices_max_width_dim   % 用于储存选项宽度的最大值
\int_new:N \l__xchoices_items_number_int  % 储存seq一共有多少项
\int_new:N \l__xchoices_env_xitem_int    % 用于xchoices环境的xitem计数
\int_zero:N \l__xchoices_env_xitem_int   % 先设初始值为0
\int_new:N \l__xchoices_items_per_line_int   % hlist环境每行排多少个
\dim_new:N \l__xchoices_linewidth_dim    % 储存当前行宽
\tl_new:N \l__xchoices_prelabel_tl    % label前面的内容
\tl_new:N \l__xchoices_hlist_label_style_tl   % label的样式
\tl_new:N \l__xchoices_postlabel_tl   % label后面的内容
\str_new:N \l__xchoices_current_label_style_str  % 储存当前的label-style
% 输出正确答案的在第几项（可能是多选，所以用seq）
\seq_new:N \l__xchoices_env_correct_items_number_seq 
\bool_new:N \__xchoices_env_show_answer_bool  % 控制最终是否要显示，不仅是为了可以手动控制，还是为了当没有设置正确答案的时候不出现“参考答案”等字样
\bool_new:N \l__xchoices_env_show_analysis_bool   % 控制是否显示解析
\tl_new:N \l__xchoices_answer_analysis_content_tl    % 答案解析的内容
\tl_new:N \l__xchoices_env_analysis_label_color_tl    % “解析”的颜色
\tl_new:N \l__xchoices_env_analysis_label_content_tl   % “解析”字样的内容，包括字体之类的，比用pre，post灵活性更高
\tl_new:N \l__xchoices_env_answer_label_color_tl    % “参考答案”的颜色
\tl_new:N \l__xchoices_env_answer_label_content_tl   % “参考答案”字样的内容，包括字体之类的，比用pre，post灵活性更高
\dim_new:N \l__xchoices_coffin_join_vertical_sep_dim     % join时的垂直偏移
\dim_new:N \l__xchoices_coffin_join_horizontal_sep_dim   % join时的水平偏移
\str_new:N \l__xchoices_coffin_current_label_pos_str     % 储存当前的label-pos
\tl_new:N \l__xchoices_coffin_typeset_horizontal_position_tl    % coffintypeset出来的水平pole
\tl_new:N \l__xchoices_coffin_typeset_verticle_position_tl    % coffintypeset出来的水平pole
\dim_new:N \l__xchoices_coffin_hlist_vsep_dim     % coffinchoices里hlist的item sep
\dim_new:N \l__xchoices_coffin_hlist_hsep_dim     % coffinchoices里hlist的col sep
\tl_new:N \l__xchoices_coffin_label_style_tl   % coffinchoices的label样式
\dim_new:N \l__xchoices_coffin_typeset_vertical_transform_dim   % coffinchoices的typeset的垂直偏移
\dim_new:N \l__xchoices_coffin_typeset_horizontal_transform_dim   % coffinchoices的typeset的水平偏移
\bool_new:N \l__xchoices_coffin_if_add_figure_bool   % 检测是否有插入图片

%% quan 相关变量
\dim_new:N \l__quan_height_of_number_dim        % quan: 储存数字的高度
\dim_new:N \l__quan_radius_of_circle_dim        % quan: 圆的半径
\fp_new:N \l__quan_xscale_of_number_fp          % quan: 数字的水平压缩比例
\fp_new:N \l__quan_yscale_of_number_fp          % quan: 数字的垂直压缩比例



% LaTeX2e命令复制

% 复制\settoheight命令
\cs_set_eq:NN \my_settoheight:Nn \settoheight  % 获取高度



% 产生变体函数
\cs_generate_variant:Nn \dim_set:Nn { Nv, cv}
\cs_generate_variant:Nn \dim_set:Nn { NV }
\cs_generate_variant:Nn \dim_max:nn { Vv }
\cs_generate_variant:Nn \seq_set_split:Nnn {NnV}
\prg_generate_conditional_variant:Nnn \str_if_eq:nn {Vn} {TF}
\cs_generate_variant:Nn \coffin_typeset:Nnnnn {cVVnn}


% 错误键值的报错信息
\msg_new:nnn { xchoices } { unknown-option }
  { package~ option~ "\l_keys_key_tl"~ is~ unknown. }

% 将计数器的值转化为number（来源于hlist宏包源码）
\cs_new:Npn \__xchoices_arabic_counter:n #1
  {
    \number\csname c@\detokenize{#1} \endcsname
  }

% 不同label-style的pre和postlabel地设置
\cs_new:Npn \__xchoices_coffin_label_style_set:n #1
  {
    \str_set:Nn \l__xchoices_current_label_style_str {#1}
    \str_if_eq:nnTF {#1} {none}
      {
        \tl_set:Nn \l__xchoices_postlabel_tl {}
        \tl_set:Nn \l__xchoices_prelabel_tl {}
      }
      {
        \str_if_eq:nnTF {#1} {chinese}
          {
            \tl_set:Nn \l__xchoices_postlabel_tl {、}
            \tl_set:Nn \l__xchoices_prelabel_tl {}
          }
          {
            \str_if_eq:nnTF {#1} { quan }
              {
                \tl_set:Nn \l__xchoices_postlabel_tl {}
                \tl_set:Nn \l__xchoices_prelabel_tl {}
              }
              {}
          }
      }
  }
% 如果是right系列就把“.”放在label前面
\cs_new:Nn \__xchoices_check_if_right:
  {
    \str_case:VnT \l__xchoices_coffin_current_label_pos_str
      {
        {right}{}
        {right-top}{}
        {right-center}{}
        {right-bottom}{}
      }
      {
        \tl_set:Nn \l__xchoices_prelabel_tl {.}
        \tl_set:Nn \l__xchoices_postlabel_tl {}
      }
  }
\keys_define:nn { xchoices / coffinchoices }
  {
    % label的位置
    label-pos .choices:nn =
      {
        top , top-left , top-center , top-right ,
        bottom , bottom-left , bottom-center , bottom-right ,
        left , left-top , left-center , left-bottom ,
        right , right-top , right-center , right-bottom
      }
      { 
        \str_set:NV \l__xchoices_coffin_current_label_pos_str \l_keys_choice_tl 
        \__xchoices_check_if_right:
      },
    label-pos .initial:n = left,
    % label样式
    label-style .code:n = 
      { \__xchoices_coffin_label_style_set:n {#1} },
    label-style .initial:n = Alph,
    % label前面的内容
    pre-label .tl_set:N = \l__xchoices_prelabel_tl,
    % label后面的内容
    post-label .tl_set:N = \l__xchoices_postlabel_tl,
    post-label .initial:n = {.},
    % label的垂直偏移量
    label-vsep .dim_set:N = \l__xchoices_coffin_join_vertical_sep_dim,
    label-vsep .initial:n = 0pt,
    % label的水平偏移量
    label-hsep .dim_set:N = \l__xchoices_coffin_join_horizontal_sep_dim,
    label-hsep .initial:n = 5pt,
    % 每行多少个
    items .int_set:N = \l__xchoices_items_per_line_int,
    % 两行之间的额外间距
    v-sep .dim_set:N = \l__xchoices_coffin_hlist_vsep_dim,
    v-sep .initial:n = 0pt,
    % 两列之间的额外间距
    h-sep .dim_set:N = \l__xchoices_coffin_hlist_hsep_dim,
    h-sep .initial:n = 0pt,
    % 是否显示答案
    showanswer .bool_set:N = \__xchoices_env_show_answer_bool,
    showanswer .default:n = true,
    showanswer .initial:n = false,
    % “参考答案”label的内容
    answer-label-content .tl_set:N = \l__xchoices_env_answer_label_content_tl,
    answer-label-content .initial:n = {【参考答案】},
    % “参考答案”label的颜色
    answer-label-color .tl_set:N = \l__xchoices_env_answer_label_color_tl,
    answer-label-color .initial:n = violet,
    % 整体的水平偏移
    h-offset .dim_set:N = \l__xchoices_coffin_typeset_horizontal_transform_dim,
    % 整体的垂直偏移
    v-offset .dim_set:N = \l__xchoices_coffin_typeset_vertical_transform_dim,
    % xchoices*环境与上方的距离
    top .dim_set:N = \l__xchoices_env_top_distance_dim,
    top .initial:n = -7pt,
    % xchoices*环境与下方的距离
    bottom .dim_set:N = \l__xchoices_env_bottom_distance_dim,
    bottom .initial:n = -5pt,
    unknown .code:n = { \msg_error:nnn { xchoices } { unknown-option } {#1} }
  }

\cs_new:Npn \__xchoices_coffin_input:NNN #1#2#3
  {
    % 新声明coffinchoices的label和content的coffin（个数？\l__xchoices_items_number_int）
    % 此时要先处理label再存（pre-label、样式、post-label）
    \__xchoices_coffin_new:N #3
      % \l__xchoices_items_number_int
    % 把seq内容存到content的coffin里
    \__xchoices_coffin_store_content:NN
      #3 #1
      % \l__xchoices_items_number_int
      % \l__xchoices_items_seq
  }


\coffin_new:N \l__xchoices_tmp_coffin

%$ 声明coffin以及处理label样式
\cs_new:Npn \__xchoices_coffin_new:N #1
  {
    \int_step_inline:nn { #1 } 
      {
        %% 新声明coffin变量
        % 存内容的coffin
        \coffin_if_exist:cF
          { l__xchoices_coffin_content_ \int_to_roman:n {##1} _coffin }
          {
            \coffin_new:c { l__xchoices_coffin_content_ \int_to_roman:n {##1} _coffin }
          }
        % 存label的coffin
        \coffin_if_exist:cF
          { l__xchoices_coffin_label_ \int_to_roman:n {##1} _coffin }
          {
            \coffin_new:c { l__xchoices_coffin_label_ \int_to_roman:n {##1} _coffin }
          }
        % 将label进行储存
        \vcoffin_set:Nnn \l__xchoices_tmp_coffin {1em}
          {
            \l__xchoices_prelabel_tl
            \__xchoices_current_label_transform_int:n {##1}
            \l__xchoices_postlabel_tl
          }
        \hcoffin_set:cn { l__xchoices_coffin_label_ \int_to_roman:n {##1} _coffin }
          {
            \l__xchoices_prelabel_tl
            \__xchoices_current_label_transform_int:n {##1}
            \l__xchoices_postlabel_tl
          }
          % {
          %   \coffin_typeset:Nnnnn 
          %     \l__xchoices_tmp_coffin
          %     {l} {T} {0pt} {0pt}
          % }
      }
  }

\cs_generate_variant:Nn \vcoffin_set:Nnn {Nvn}


% 把seq中的选项存到coffin里
% #1: seq的个数
% #2: 要储存的那个seq
\cs_new:Npn \__xchoices_coffin_store_content:NN #1#2
  {
    \int_step_inline:nn {#1}
      {
        \vcoffin_set:Nvn \l__xchoices_tmp_coffin
          {
            l__xchoices_measure_width_ \int_to_roman:n {##1} _dim
          }
          {
            \seq_item:Nn #2 {##1} 
          }
        \hcoffin_set:cn { l__xchoices_coffin_content_ \int_to_roman:n {##1} _coffin }
          % { \seq_item:Nn #2 {##1} }
          {
            \coffin_typeset:Nnnnn 
              \l__xchoices_tmp_coffin
              {l} {T} {0pt} {0pt}
          }
      }
  }


% 确定join方式
% \__xchoices_coffin_join:N \l__xchoices_items_number_int
% #1: seq的个数
\cs_new:Npn \__xchoices_coffin_join:N #1
  {
    \int_step_inline:nn {#1}
      {
        \use:c { __xchoices_label_pos_set_ \l__xchoices_coffin_current_label_pos_str :ccc }
          { l__xchoices_coffin_label_ \int_to_roman:n {##1} _coffin }
          { l__xchoices_coffin_content_ \int_to_roman:n {##1} _coffin }
          { l__xchoices_measure_height_ \int_to_roman:n {##1} _dim }
      }
  }


\cs_new:cpn { __xchoices_label_pos_set_top-center:NNN } #1#2#3
  {
    \coffin_join:NnnNnnnn
      #1 { b } { hc }
      #2 { t } { hc }
      { \l__xchoices_coffin_join_horizontal_sep_dim }
      { -0.5em + \l__xchoices_coffin_join_vertical_sep_dim }
    % typeset的水平pole
    \tl_set:Nn \l__xchoices_coffin_typeset_horizontal_position_tl { hc }
    % typeset的垂直pole
    \tl_set:Nn \l__xchoices_coffin_typeset_verticle_position_tl { t }
    % 两行之间的垂直偏移量
    \dim_set:Nn \l__xchoices_coffin_hlist_vsep_dim { 0em }
    % typeset的水平偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_horizontal_transform_dim
      {
        \int_case:nnF { \l__xchoices_items_per_line_int }
          {
            {1} { 0.5 \linewidth }
            {2} { 0.25 \linewidth }
            {3} { 0.165 \linewidth }
            {4} { 0.125 \linewidth }
          }
          { 0.1 \linewidth }
      }
    % typeset的垂直偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_vertical_transform_dim 
      { 0em }
  }


\cs_set_eq:cc { __xchoices_label_pos_set_top:NNN } 
{ __xchoices_label_pos_set_top-center:NNN }


\cs_new:cpn { __xchoices_label_pos_set_top-left:NNN } #1#2#3
  {
    \coffin_join:NnnNnnnn
      #1 { b } { l }
      #2 { t } { l }
      { \l__xchoices_coffin_join_horizontal_sep_dim }
      { -4pt + \l__xchoices_coffin_join_vertical_sep_dim }
    % typeset的水平pole
    \tl_set:Nn \l__xchoices_coffin_typeset_horizontal_position_tl { l }
    % typeset的垂直pole
    \tl_set:Nn \l__xchoices_coffin_typeset_verticle_position_tl { t }
    % 两行之间的垂直偏移量
    \dim_set:Nn \l__xchoices_coffin_hlist_vsep_dim { 0em }
    % typeset的水平偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_horizontal_transform_dim 
      {
        \int_case:nnF { \l__xchoices_items_per_line_int }
          {
            {1} { 0 \linewidth }
            {2} { 0 \linewidth }
            {3} { 0 \linewidth }
            {4} { 0 \linewidth }
          }
          { 0 \linewidth }
      }
    % typeset的垂直偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_vertical_transform_dim 
      { 0em }
  }


\cs_new:cpn { __xchoices_label_pos_set_top-right:NNN } #1#2#3
  {
    \coffin_join:NnnNnnnn
      #1 { b } { r }
      #2 { t } { r }
      { \l__xchoices_coffin_join_horizontal_sep_dim }
      { -5pt + \l__xchoices_coffin_join_vertical_sep_dim }
    % typeset的水平pole
    \tl_set:Nn \l__xchoices_coffin_typeset_horizontal_position_tl { r }
    % typeset的垂直pole
    \tl_set:Nn \l__xchoices_coffin_typeset_verticle_position_tl { t }
    % 两行之间的垂直偏移量
    \dim_set:Nn \l__xchoices_coffin_hlist_vsep_dim { 0em }
    % typeset的水平偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_horizontal_transform_dim 
      {
        \int_case:nnF { \l__xchoices_items_per_line_int }
          {
            {1} { 1 \linewidth }
            {2} { 0.5 \linewidth }
            {3} { 0.33 \linewidth }
            {4} { 0.25 \linewidth }
          }
          { 0.2 \linewidth }
      }
    % typeset的垂直偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_vertical_transform_dim 
      { 0em }
  }


\cs_new:cpn { __xchoices_label_pos_set_bottom:NNN } #1#2#3
  {
    \coffin_join:NnnNnnnn
      #1 { t } { hc }
      #2 { b } { hc }
      { \l__xchoices_coffin_join_horizontal_sep_dim }
      { 5pt + \l__xchoices_coffin_join_vertical_sep_dim }
    % typeset的水平pole
    \tl_set:Nn \l__xchoices_coffin_typeset_horizontal_position_tl { hc }
    % typeset的垂直pole
    \tl_set:Nn \l__xchoices_coffin_typeset_verticle_position_tl { b }
    % 两行之间的垂直偏移量
    \dim_set:Nn \l__xchoices_coffin_hlist_vsep_dim { 0em }
    % typeset的水平偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_horizontal_transform_dim 
      {
        \int_case:nnF { \l__xchoices_items_per_line_int }
          {
            {1} { 0.5 \linewidth }
            {2} { 0.25 \linewidth }
            {3} { 0.165 \linewidth }
            {4} { 0.125 \linewidth }
          }
          { 0.1 \linewidth }
      }
    % typeset的垂直偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_vertical_transform_dim 
      { 0em }
  }


\cs_set_eq:cc { __xchoices_label_pos_set_bottom-center:NNN } 
  { __xchoices_label_pos_set_bottom:NNN }


\cs_new:cpn { __xchoices_label_pos_set_bottom-left:NNN } #1#2#3
  {
    \coffin_join:NnnNnnnn
      #1 { t } { l }
      #2 { b } { l }
      { \l__xchoices_coffin_join_horizontal_sep_dim }
      { 5pt + \l__xchoices_coffin_join_vertical_sep_dim }
    % typeset的水平pole
    \tl_set:Nn \l__xchoices_coffin_typeset_horizontal_position_tl { l }
    % typeset的垂直pole
    \tl_set:Nn \l__xchoices_coffin_typeset_verticle_position_tl { b }
    % 两行之间的垂直偏移量
    \dim_set:Nn \l__xchoices_coffin_hlist_vsep_dim { 0em }
    % typeset的水平偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_horizontal_transform_dim 
      {
        \int_case:nnF { \l__xchoices_items_per_line_int }
          {
            {1} { 0 \linewidth }
            {2} { 0 \linewidth }
            {3} { 0 \linewidth }
            {4} { 0 \linewidth }
          }
          { 0 \linewidth }
      }
    % typeset的垂直偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_vertical_transform_dim 
      { 0em }
  }


\cs_new:cpn { __xchoices_label_pos_set_bottom-right:NNN } #1#2#3
  {
    \coffin_join:NnnNnnnn
      #1 { t } { r }
      #2 { b } { r }
      { \l__xchoices_coffin_join_horizontal_sep_dim }
      { 5pt + \l__xchoices_coffin_join_vertical_sep_dim }
    % typeset的水平pole
    \tl_set:Nn \l__xchoices_coffin_typeset_horizontal_position_tl { r }
    % typeset的垂直pole
    \tl_set:Nn \l__xchoices_coffin_typeset_verticle_position_tl { b }
    % 两行之间的垂直偏移量
    \dim_set:Nn \l__xchoices_coffin_hlist_vsep_dim { 0em }
    % typeset的水平偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_horizontal_transform_dim 
      {
        \int_case:nnF { \l__xchoices_items_per_line_int }
          {
            {1} { 1 \linewidth }
            {2} { 0.5 \linewidth }
            {3} { 0.33 \linewidth }
            {4} { 0.25 \linewidth }
          }
          { 0.2 \linewidth }
      }
    % typeset的垂直偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_vertical_transform_dim 
      { 0em }
  }


\cs_new:cpn { __xchoices_label_pos_set_left:NNN } #1#2#3
  {
    \dim_compare:nNnTF {#3} > { \baselineskip }
      {
        \coffin_join:NnnNnnnn
        #1 { H } { r }
        #2 { vc } { l }
        { 0pt + \l__xchoices_coffin_join_horizontal_sep_dim }
        { 2pt + \l__xchoices_coffin_join_vertical_sep_dim }
      }
      {
        \coffin_join:NnnNnnnn
          #1 { H } { r }
          #2 { H } { l }
          { 0pt + \l__xchoices_coffin_join_horizontal_sep_dim }
          { \l__xchoices_coffin_join_vertical_sep_dim }
      }
    % typeset的水平pole
    \tl_set:Nn \l__xchoices_coffin_typeset_horizontal_position_tl { l }
    % typeset的垂直pole
    \tl_set:Nn \l__xchoices_coffin_typeset_verticle_position_tl { vc }
    % 两行之间的垂直偏移量
    \dim_set:Nn \l__xchoices_coffin_hlist_vsep_dim { -0.5em }
    % typeset的水平偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_horizontal_transform_dim 
      {
        \int_case:nnF { \l__xchoices_items_per_line_int }
          {
            {1} { 0 \linewidth }
            {2} { 0 \linewidth }
            {3} { 0 \linewidth }
            {4} { 0 \linewidth }
          }
          { 0 \linewidth }
      }
    % typeset的垂直偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_vertical_transform_dim 
      { 0em }
  }


\cs_set_eq:cc 
  { __xchoices_label_pos_set_left-center:NNN } 
  { __xchoices_label_pos_set_left:NNN }


\cs_new:cpn { __xchoices_label_pos_set_left-top:NNN } #1#2#3
  {
    \coffin_join:NnnNnnnn
      #1 { t } { r }
      #2 { t } { l }
      { \l__xchoices_coffin_join_horizontal_sep_dim }
      { 0pt + \l__xchoices_coffin_join_vertical_sep_dim }
    % typeset的水平pole
    \tl_set:Nn \l__xchoices_coffin_typeset_horizontal_position_tl { l }
    % typeset的垂直pole
    \tl_set:Nn \l__xchoices_coffin_typeset_verticle_position_tl { t }
    % 两行之间的垂直偏移量
    \dim_set:Nn \l__xchoices_coffin_hlist_vsep_dim { 0em }
    % typeset的水平偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_horizontal_transform_dim 
      {
        \int_case:nnF { \l__xchoices_items_per_line_int }
          {
            {1} { 0 \linewidth }
            {2} { 0 \linewidth }
            {3} { 0 \linewidth }
            {4} { 0 \linewidth }
          }
          { 0 \linewidth }
      }
    % typeset的垂直偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_vertical_transform_dim 
      { 0em }
  }


\cs_new:cpn { __xchoices_label_pos_set_left-bottom:NNN } #1#2#3
  {
    \coffin_join:NnnNnnnn
      #1 { b } { r }
      #2 { b } { l }
      { \l__xchoices_coffin_join_horizontal_sep_dim }
      { \l__xchoices_coffin_join_vertical_sep_dim }
    % typeset的水平pole
    \tl_set:Nn \l__xchoices_coffin_typeset_horizontal_position_tl { l }
    % typeset的垂直pole
    \tl_set:Nn \l__xchoices_coffin_typeset_verticle_position_tl { b }
    % 两行之间的垂直偏移量
    \dim_set:Nn \l__xchoices_coffin_hlist_vsep_dim { 0.5em }
    % typeset的水平偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_horizontal_transform_dim 
      {
        \int_case:nnF { \l__xchoices_items_per_line_int }
          {
            {1} { 0 \linewidth }
            {2} { 0 \linewidth }
            {3} { 0 \linewidth }
            {4} { 0 \linewidth }
          }
          { 0 \linewidth }
      }
    % typeset的垂直偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_vertical_transform_dim 
      { 0em }
  }


\cs_new:cpn { __xchoices_label_pos_set_right:NNN } #1#2#3
  {
    \coffin_join:NnnNnnnn
      #1 { vc } { l }
      #2 { vc } { r }
      { -10pt + \l__xchoices_coffin_join_horizontal_sep_dim }
      { \l__xchoices_coffin_join_vertical_sep_dim }
    % typeset的水平pole
    \tl_set:Nn \l__xchoices_coffin_typeset_horizontal_position_tl { r }
    % typeset的垂直pole
    \tl_set:Nn \l__xchoices_coffin_typeset_verticle_position_tl { vc }
    % 两行之间的垂直偏移量
    \dim_set:Nn \l__xchoices_coffin_hlist_vsep_dim {-0.5em }
    % typeset的水平偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_horizontal_transform_dim 
      {
        \int_case:nnF { \l__xchoices_items_per_line_int }
          {
            {1} { 1 \linewidth }
            {2} { 0.5 \linewidth }
            {3} { 0.33 \linewidth }
            {4} { 0.25 \linewidth }
          }
          { 0.2 \linewidth }
      }
    % typeset的垂直偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_vertical_transform_dim 
      { 0em }
  }


\cs_set_eq:cc 
  { __xchoices_label_pos_set_right-center:NNN } 
  { __xchoices_label_pos_set_right:NNN }


\cs_new:cpn { __xchoices_label_pos_set_right-top:NNN } #1#2#3
  {
    \coffin_join:NnnNnnnn
      #1 { t } { l }
      #2 { t } { r }
      { -10pt + \l__xchoices_coffin_join_horizontal_sep_dim }
      { \l__xchoices_coffin_join_vertical_sep_dim }
    % typeset的水平pole
    \tl_set:Nn \l__xchoices_coffin_typeset_horizontal_position_tl { r }
    % typeset的垂直pole
    \tl_set:Nn \l__xchoices_coffin_typeset_verticle_position_tl { t }
    % 两行之间的垂直偏移量
    \dim_set:Nn \l__xchoices_coffin_hlist_vsep_dim { 0em }
    % typeset的水平偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_horizontal_transform_dim 
      {
        \int_case:nnF { \l__xchoices_items_per_line_int }
          {
            {1} { 1 \linewidth }
            {2} { 0.5 \linewidth }
            {3} { 0.33 \linewidth }
            {4} { 0.25 \linewidth }
          }
          { 0.2 \linewidth }
      }
    % typeset的垂直偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_vertical_transform_dim 
      { 0em }
  }


\cs_new:cpn { __xchoices_label_pos_set_right-bottom:NNN } #1#2#3
  {
    \coffin_join:NnnNnnnn
      #1 { b } { l }
      #2 { b } { r }
      { -10pt + \l__xchoices_coffin_join_horizontal_sep_dim }
      { \l__xchoices_coffin_join_vertical_sep_dim }
    % typeset的水平pole
    \tl_set:Nn \l__xchoices_coffin_typeset_horizontal_position_tl { r }
    % typeset的垂直pole
    \tl_set:Nn \l__xchoices_coffin_typeset_verticle_position_tl { b }
    % 两行之间的垂直偏移量
    \dim_set:Nn \l__xchoices_coffin_hlist_vsep_dim { 0em }
    % typeset的水平偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_horizontal_transform_dim 
      {
        \int_case:nnF { \l__xchoices_items_per_line_int }
          {
            {1} { 1 \linewidth }
            {2} { 0.5 \linewidth }
            {3} { 0.33 \linewidth }
            {4} { 0.25 \linewidth }
          }
          { 0.2 \linewidth }
      }
    % typeset的垂直偏移
    \dim_set:Nn \l__xchoices_coffin_typeset_vertical_transform_dim 
      { 0em }
  }


% 产生变体
\clist_map_inline:nn
  {
    top , top-left , top-center , top-right ,
    bottom , bottom-left , bottom-center , bottom-right ,
    left , left-top , left-center , left-bottom ,
    right , right-top , right-center , right-bottom
  }
  {
    \cs_generate_variant:cn
      { __xchoices_label_pos_set_ #1 :NNN } { ccc }
  }


% 把coffin按照自动计算的每行个数typeset出来（命令关键点）
% #1: 每行个数
% #2: 一共的项数
\cs_new:Npn \__xchoices_coffin_typeset:NN #1#2
  {
    \begin{hlist}
      [
        show~label = false,
        pre~label   = ,           % 使得label没有加粗效果
        label~align = right,      % label的默认对齐方式是右对齐
        label~sep   = 0pt,
        left~margin = 0pt,
        item~offset = 0pt,
        item~sep = 
          {
            \dim_eval:n { 1em + \l__xchoices_coffin_hlist_vsep_dim }
          },
        col~sep = 
          {
            \dim_eval:n { 0em + \l__xchoices_coffin_hlist_hsep_dim }
          }
      ]#1
      \int_step_inline:nn {#2}
        { 
          \hitem
          \coffin_typeset:cVVnn 
            { l__xchoices_coffin_label_ \int_to_roman:n {##1} _coffin }
            \l__xchoices_coffin_typeset_horizontal_position_tl
            \l__xchoices_coffin_typeset_verticle_position_tl
            { \l__xchoices_coffin_typeset_horizontal_transform_dim } 
            { \l__xchoices_coffin_typeset_vertical_transform_dim }
        }
    \end{hlist}
  }


% 最终将seq传入的函数
\cs_new:Npn \__xchoices_handle_seq_after_check:N #1
  {
    % 将seq的项数进行储存，将seq的每一项都拿出来，储存到box中的varwidth环境里
    \__xchoices_store_items_and_width_of_seq_in_box:NN
      #1 \l__xchoices_items_number_int
    % 测量宽度，获取最大值
    \__xchoices_get_max_width:NNN
      \l__xchoices_max_width_dim
      \l__xchoices_measure_width_i_dim
      \l__xchoices_items_number_int
    % 根据最大值，确定每行排版的个数
    % \__xchoices_auto_items_calc:NNN
    \__xchoices_auto_items_calc:NNN
      \l__xchoices_items_per_line_int
      \l__xchoices_max_width_dim
      \l__xchoices_linewidth_dim
  }


% 测量选项宽度的最大值
\cs_new:Npn \__xchoices_get_max_width:NNN #1#2#3
  % #1: 最大宽度储存变量
  % #2: 第一个选项的变量（先“初始化”max_dim）
  % #3: 选项的项数
  {
    % 先把第一个选项的值赋值给max_dim
    \dim_set_eq:NN #1 #2
    \int_step_inline:nn {#3}
      {
        \dim_set:Nn #1
          {
            \dim_max:Vv #1
              { l__xchoices_measure_width_ \int_to_roman:n {##1} _dim }
          }
      }
  }


% 将最大宽度与行宽进行比较决定每行排多少个
\cs_new:Npn \__xchoices_auto_items_calc:NNN #1#2#3
  % #1: 每行的个数int变量
  % #2: 最大宽度
  % #3: 行宽
  % #4: > #4行宽排每行一个
  % #5: #2 行宽～ #4行宽 每行两个
  {
    % 先储存行宽
    \dim_set_eq:NN #3 \linewidth
    % 比较最大宽度与行宽
    \dim_compare:nNnTF {#2} > { 0.45 #3 }
      { \int_set:Nn #1 {1} }
      {
        \dim_compare:nNnTF {#2} > { 0.2 #3 }
          { \int_set:Nn #1 {2} }
          { \int_set:Nn #1 {4} }
      }
  }


% 储存seq的项到box变量，并将长度进行储存到dim变量
\cs_new:Npn \__xchoices_store_items_and_width_of_seq_in_box:NN #1#2
% #1: 要储存的seq变量
% #2: 项数储存的int变量
  {
    % 先储存seq的项数
    \int_set:Nn #2 { \seq_count:N #1 }
    % 循环遍历
    \int_step_inline:nn { #2 }
      {
        % box变量的声明，用来储存seq的每一项内容
        % 之所以要先判断是否存在，是因为new出来的变量是全局的
        % 如果只是new的话，第二次使用就会出现already define的报错，下面的dim的声明也是同理
        \box_if_exist:cF
          { l__xchoices_measure_width_ \int_to_roman:n {##1} _box }
          {
            % 不存在的话就新定义
            \box_new:c { l__xchoices_measure_width_ \int_to_roman:n {##1} _box }
          }
        % 声明dim变量存宽度
        \dim_if_exist:cF
          { l__xchoices_measure_width_ \int_to_roman:n {##1} _dim}
          {
            % 不存在的话就新定义
            \dim_new:c { l__xchoices_measure_width_ \int_to_roman:n {##1} _dim }
          }
        % 声明dim变量存高度
        \dim_if_exist:cF
          { l__xchoices_measure_height_ \int_to_roman:n {##1} _dim}
          {
            % 不存在的话就新定义
            \dim_new:c { l__xchoices_measure_height_ \int_to_roman:n {##1} _dim }
          }
        % 把每个选项存到对应的盒子里
        \hbox_set:cn { l__xchoices_measure_width_ \int_to_roman:n {##1} _box }
          {
            \begin{varwidth}{\hsize}
              \seq_item:Nn #1 {##1} 
            \end{varwidth}
          }
        % 把选项的长度进行储存
        \dim_set:cn { l__xchoices_measure_width_ \int_to_roman:n {##1} _dim }
          {
            \box_wd:c { l__xchoices_measure_width_ \int_to_roman:n {##1} _box }
          }
        % 把选项的高度进行储存
        \dim_set:cn { l__xchoices_measure_height_ \int_to_roman:n {##1} _dim }
          {
            \box_ht:c { l__xchoices_measure_width_ \int_to_roman:n {##1} _box }
          }
      }
  }


\seq_new:N \l__xchoices_env_items_seq   % 用来存环境的seq

\cs_new:Npn \__xchoices_env_pre_store_label:N #1
  {
    % 用来存label的
    \coffin_if_exist:cF
      { l__xchoices_coffin_label_ \int_to_roman:n { #1 } _coffin }
      {
        \coffin_new:c { l__xchoices_coffin_label_ \int_to_roman:n { #1 } _coffin }
      }
    \vcoffin_set:Nnn \l__xchoices_tmp_coffin {1em}
      {
        \l__xchoices_prelabel_tl
        \__xchoices_current_label_transform_int:n { \int_use:N #1 }
        \l__xchoices_postlabel_tl
      }
    \hcoffin_set:cn { l__xchoices_coffin_label_ \int_to_roman:n { #1 } _coffin }
      {
        \l__xchoices_prelabel_tl
        \__xchoices_current_label_transform_int:n { \int_use:N #1 }
        \l__xchoices_postlabel_tl
      }
    % 存 label的宽度
    \dim_if_exist:cF
      { l__xchoices_label_width_ \int_to_roman:n { #1 } _dim}
      {
        % 不存在的话就新定义
        \dim_new:c { l__xchoices_label_width_ \int_to_roman:n { #1  } _dim }
      }
    \dim_set:cn { l__xchoices_label_width_ \int_to_roman:n { #1  } _dim }
      {
        \coffin_wd:c { l__xchoices_coffin_label_ \int_to_roman:n { #1 } _coffin }
      }
  }


\cs_new:Nn \__xchoices_env_xitem_new:
  {
    % 如果是第一项的话就不需要\__xchoices_env_xitem_out:
    % 只有第二项开始才需要处理上一个
    \int_compare:nNnF { \l__xchoices_env_xitem_int } = { 0 }
      { \__xchoices_env_xitem_out: }
    % xitem计数器的值+1
    \int_incr:N \l__xchoices_env_xitem_int
    % 测试一下是否存在了对应值的box，不存在的话新声明一个
    % 用来存选项内容
    \box_if_exist:cF { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _box }
      {
        \box_new:c { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _box }
      }
    % 用来标记此选项是不是正确答案
    \bool_if_exist:cF { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _bool}
      {
        \bool_new:c { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _bool }
      }
    % 储存label
    \__xchoices_env_pre_store_label:N \l__xchoices_env_xitem_int
    % 将错误答案对应项数的bool设置为false
    \bool_set_false:c { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _bool}
    \hbox_set:cw { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _box }
      % \begin{varwidth}[t]{\hsize}
      % 调整宽度：行宽-label宽-leftmargin
      \begin{varwidth}[t]{ \dim_eval:n{ \linewidth - \use:c { l__xchoices_label_width_ \int_to_roman:n { \l__xchoices_env_xitem_int  } _dim } - \l__xchoices_coffin_join_horizontal_sep_dim } }
  }


% 用来设置标记为正确答案的选项
\cs_new:Nn \__xchoices_env_xitem_new_correct:
  {
    % 如果是第一项的话就不需要\__xchoices_env_xitem_out:
    % 只有第二项开始才需要处理上一个
    \int_compare:nNnF { \l__xchoices_env_xitem_int } = { 0 }
    { \__xchoices_env_xitem_out: }
    % xitem计数器的值+1
    \int_incr:N \l__xchoices_env_xitem_int
    % 测试一下是否存在了对应值的box，不存在的话新声明一个
    % 用来存选项内容
    \box_if_exist:cF { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _box }
      {
        \box_new:c { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _box }
      }
    % 用来标记此选项是不是正确答案
    \bool_if_exist:cF { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _bool}
      {
        \bool_new:c { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _bool }
      }
    % 储存label
    \__xchoices_env_pre_store_label:N \l__xchoices_env_xitem_int
    % 将错误答案对应项数的bool设置为true
    \bool_set_true:c { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _bool}
    \hbox_set:cw { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _box }
      % \begin{varwidth}[t]{\hsize}
      % 调整宽度：行宽-label宽-leftmargin
      \begin{varwidth}[t]{ \dim_eval:n{ \linewidth - \use:c { l__xchoices_label_width_ \int_to_roman:n { \l__xchoices_env_xitem_int  } _dim } - \l__xchoices_coffin_join_horizontal_sep_dim } }
  }


\cs_new:Nn \__xchoices_env_xitem_out:
  {
      \end{varwidth}
    \hbox_set_end:
    % 把储存好内容的box传到seq里面
    \seq_put_right:Nx \l__xchoices_env_items_seq 
      { 
        \box_use:c { l__xchoices_env_ \int_to_roman:n { \l__xchoices_env_xitem_int } _box } 
      }
  }

% 用来储存正确items的项数
\cs_new:Nn \__xchoices_env_output_correct_items_number_to_seq:
  {
    \int_step_inline:nn { \l__xchoices_items_number_int }
      {
        % 如果对应的bool是正确的就把这个数字存到\l__xchoices_env_correct_items_number_seq
        \bool_if:cT { l__xchoices_env_ \int_to_roman:n {##1} _bool}
          {
            \seq_put_right:Nn \l__xchoices_env_correct_items_number_seq {##1}
          }
      }
  }


\cs_new:Npn \__xchoices_env_show_correct_answer:N #1
  {
    \bool_if:NT \__xchoices_env_show_answer_bool
      {
        % \vspace*{1em}
        \noindent
        \textcolor
          { \tl_use:N \l__xchoices_env_answer_label_color_tl}
          { \tl_use:N \l__xchoices_env_answer_label_content_tl }
        %% 先将正确答案seq的数字用当前的label-style转换一下
        \__xchoices_env_correct_number_transform_by_label_style:N #1
        % 只用循环的话会造成最后一项最后也有, 
        % \seq_map_inline:Nn #1 {##1~}
        % 采用seq_use的方法
        % 三个{} 内依次是：只有两个的之间的、超过两个时前面几个之间的、超过两个时最后两个直接的
        % \seq_use:Nnnn #1 { ~and~ } { ,~ } { ,~and~ }
        \seq_use:Nnnn #1 { ,~ } { ,~ } { ,~ }
        \par
      }
  }


\seq_new:N \l__xchoices_tmpa_seq   % 临时变量

\cs_new:Npn \__xchoices_env_correct_number_transform_by_label_style:N #1
  {
    % 先把#1seq的map-inline的方式通过label-style转化储存到\l__xchoices_tmpa_seq
    \seq_map_inline:Nn #1
      {
        \seq_put_right:Nx \l__xchoices_tmpa_seq
          {
            \__xchoices_current_label_transform_int:n {##1}
          }
      }
    % 然后再令#1和\l__xchoices_tmpa_seq相等
    \seq_set_eq:NN #1 \l__xchoices_tmpa_seq
    % 然后清空\l__xchoices_tmpa_seq
    \seq_clear:N \l__xchoices_tmpa_seq
  }


\cs_new:Npn \__xchoices_current_label_transform_int:n #1
  {
    \str_if_eq:VnTF \l__xchoices_current_label_style_str {none}
      {}
      {
        \str_if_eq:VnTF \l__xchoices_current_label_style_str {chinese}
          { \zhnumber{#1} }
          {
            \str_if_eq:VnTF \l__xchoices_current_label_style_str {quan}
            { \quan{#1} }
            {
              \str_if_eq:VnTF \l__xchoices_current_label_style_str {arabic}
                {#1}
                {
                  \use:c { int_to_ \l__xchoices_current_label_style_str :n }{#1}
                }
            }
          }
      }
  }


\tl_new:N \l__xchoices_label_hsep_init_tl    % 用于辅助判断

\cs_new:Npn \__xchoices_label_hsep_init:N #1
  {
    \str_if_in:NnTF #1 {left}
      {
        \tl_set:Nn \l__xchoices_label_hsep_init_tl {5pt}
      }
      {
        \str_if_in:NnTF #1 {right}
          {
            \tl_set:Nn \l__xchoices_label_hsep_init_tl {-5pt}
          }
          {
            \tl_set:Nn \l__xchoices_label_hsep_init_tl {0pt}
          }
      }
    \dim_set:NV
      \l__xchoices_coffin_join_horizontal_sep_dim
      \l__xchoices_label_hsep_init_tl
  }


\NewDocumentEnvironment { xchoices } { O{} }
  {
    \group_begin:
      \RenewDocumentCommand { \item } { s }
        {
          \IfBooleanTF{##1}
            { \__xchoices_env_xitem_new_correct: }
            { \__xchoices_env_xitem_new: }
        }
      \keys_set:nn { xchoices / coffinchoices } {#1}
      \vspace*{ \l__xchoices_env_top_distance_dim }
      \mode_leave_vertical:
      \int_zero:N \l__xchoices_env_xitem_int   % 先将xitem计数器设置为0
      \tl_clear:N \l__xchoices_answer_analysis_content_tl
  }
  {
      \__xchoices_env_xitem_out:
      % 根据宽度获取每行排版个数
      \__xchoices_handle_seq_after_check:N
        \l__xchoices_env_items_seq
      % 将正确答案进行储存输出
      \__xchoices_env_output_correct_items_number_to_seq:
      % 新声明coffin并且进行内容的储存
      \__xchoices_coffin_input:NNN
        \l__xchoices_env_items_seq
        \l__xchoices_items_per_line_int
        \l__xchoices_items_number_int
      % 根据当前的label-pos（采用text-figure类似的上下左右）决定如何join
      \__xchoices_coffin_join:N \l__xchoices_items_number_int
      % 此处再放一个key-set是因为上一步join里面根据前一个的key-set的label-pos设置了v-sep和h-sep
      % 第一个key-set无法干预v-sep和h-sep的设置
      % 所以在此处再设置一个
      \keys_set:nn { xchoices / coffinchoices } {#1}
      % 把coffin给type出来
      \__xchoices_coffin_typeset:NN
        \l__xchoices_items_per_line_int
        \l__xchoices_items_number_int
      \__xchoices_env_show_correct_answer:N
        \l__xchoices_env_correct_items_number_seq
      \vspace*{ \l__xchoices_env_bottom_distance_dim }
    \group_end:
  }


\NewDocumentCommand{ \xchoicesetup }{ m }
  {
    \keys_set:nn { xchoices / coffinchoices } {#1}
  }


% 带圈数字
\NewDocumentCommand{ \quan }{ m }
  {
    % 根据数字大小设置压缩系数
    \fp_set:Nn \l__quan_xscale_of_number_fp
      {
        \int_compare:nNnTF {#1} < { 10 } 
          { 0.9 }
          {
            \int_compare:nNnTF {#1} < { 100 }
              { 0.7 }
              { 0.5 }
          } 
      }
    \fp_set:Nn \l__quan_yscale_of_number_fp
      {
        \int_compare:nNnTF {#1} < { 10 } 
          { 0.9 }
          {
            \int_compare:nNnTF {#1} < { 100 }
              { 0.8 }
              { 0.6 }
          } 
      }
    % 获取数字的高度
    \my_settoheight:Nn \l__quan_height_of_number_dim {#1}
    % 设置圆的半径
    \dim_set:Nn \l__quan_radius_of_circle_dim 
      { \dim_eval:n { \l__quan_height_of_number_dim / 2 + 0.34 ex } }
    % 绘制
    \tikz[baseline]
      {
        \node at (0, \dim_use:N \l__quan_height_of_number_dim / 2 ) 
          {
            \makebox[0.35em][c]
              { 
                \scalebox { \fp_use:N \l__quan_xscale_of_number_fp } 
                [ \fp_use:N \l__quan_yscale_of_number_fp ] 
                  {
                    \int_compare:nNnTF {#1} > {99}
                      { \textbf {#1} }
                      {#1}
                  } 
              }
          };
        \draw (0, \dim_use:N \l__quan_height_of_number_dim / 2 )
          circle ( \l__quan_radius_of_circle_dim );
      }
  }


% \xparen 
\NewDocumentCommand{ \xparen } {  }
  {
    \group_begin:
      % \keys_set:nn { paren-answer } {#1}
      \tl_set:Nn \l__xparen_answer_tl
        { \qquad }
      \dim_set_eq:NN \l_tmpa_dim \linegoal
      \dim_compare:nNnT { \l_tmpa_dim } < { \textwidth/50 }
        { \par }
      \hfill \makebox{(\tl_use:N \l__xparen_answer_tl)}
    \group_end:
  }